package com.gitee.wsl.android.ui.sample.clipimage

import android.animation.ValueAnimator
import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Path
import android.graphics.Region
import android.os.Build
import android.os.Parcelable
import android.util.AttributeSet
import android.view.View
import androidx.core.animation.addListener
import kotlin.math.hypot

/**
 * 切换语言或主题通常需要重新启动 Activity 以重新加载配置。虽然 recreate 是一种常用的重建 Activity 方法，但它不支持像在 Activity 之间切换时那样使用过渡动画。特别是在切换 浅色/深色 主题时，由于缺乏过渡动画而显得很生硬。为了提升改善这一点，只能自己实现过渡动画以提供更流畅的用户体验。
 * https://juejin.cn/post/7335959102487003186?share_token=e54e9364-31b6-4a29-831b-26229d879b14
 */

class ClipImageView : androidx.appcompat.widget.AppCompatImageView {


    enum class ClipType {

        CIRCLE,

        CIRCLE_REVERSE,
    }


    private var clipType = ClipType.CIRCLE


    private var clipPath = Path()

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)


    fun clearClip() {
        clipPath.reset()
        invalidate()
    }


    fun clipCircle(centerX: Float, centerY: Float, radius: Float, clipType: ClipType) {
        clipPath.reset()
        clipPath.addCircle(centerX, centerY, radius, Path.Direction.CW)
        this.clipType = clipType
        invalidate()
    }

    override fun onDraw(canvas: Canvas) {
        if (!clipPath.isEmpty) {
            canvas.save()
            when (clipType) {
                ClipType.CIRCLE -> {

                    canvas.clipPath(clipPath)
                }

                ClipType.CIRCLE_REVERSE -> {

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        canvas.clipOutPath(clipPath)
                    } else {
                        canvas.clipPath(clipPath, Region.Op.DIFFERENCE)
                    }
                }
            }
        }

        super.onDraw(canvas)

        if (!clipPath.isEmpty) {
            canvas.restore()
        }
    }

}

enum class TransitionType {

    ENTER,


    EXIT
}


class TransitionData(
    val centerX: Float,
    val centerY: Float,
    val screenBitmap: Bitmap,
    val type: TransitionType,
) : Parcelable {
    constructor(parcel: android.os.Parcel) : this(
        parcel.readFloat(),
        parcel.readFloat(),
        parcel.readParcelable(Bitmap::class.java.classLoader)!!,
        TransitionType.valueOf(parcel.readString()!!)
    )

    override fun writeToParcel(parcel: android.os.Parcel, flags: Int) {
        parcel.writeFloat(centerX)
        parcel.writeFloat(centerY)
        parcel.writeParcelable(screenBitmap, flags)
        parcel.writeString(type.name)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<TransitionData> {
        override fun createFromParcel(parcel: android.os.Parcel): TransitionData {
            return TransitionData(parcel)
        }

        override fun newArray(size: Int): Array<TransitionData?> {
            return arrayOfNulls(size)
        }
    }
}




/**
 * 过渡动画
 */
fun Activity.transitionAnimation(ivTransition: ClipImageView, transitionData: TransitionData) {

    ivTransition.visibility = View.VISIBLE
    ivTransition.setImageBitmap(transitionData.screenBitmap)

    ivTransition.post {
        val animator = ValueAnimator.ofFloat()
        var clipType = ClipImageView.ClipType.CIRCLE
        when (transitionData.type) {
            TransitionType.ENTER -> {

                animator.setFloatValues(
                    0f,
                    hypot(ivTransition.width.toFloat(), ivTransition.height.toFloat())
                )
                clipType = ClipImageView.ClipType.CIRCLE_REVERSE
            }

            TransitionType.EXIT -> {

                animator.setFloatValues(
                    hypot(
                        ivTransition.width.toFloat(),
                        ivTransition.height.toFloat()
                    ),
                    0f
                )
                clipType = ClipImageView.ClipType.CIRCLE
            }
        }
        animator.duration =
            resources.getInteger(android.R.integer.config_longAnimTime).toLong()
        animator.addListener(
            onEnd = {

                ivTransition.visibility = View.GONE
            }
        )
        animator.addUpdateListener {
            val radius = it.animatedValue as Float

            ivTransition.clipCircle(
                transitionData.centerX,
                transitionData.centerY,
                radius,
                clipType
            )
        }
        animator.start()
    }
}

//sample
/**
 *     private lateinit var toolbar: Toolbar
 *     private lateinit var ivTransition: ClipImageView
 *
 *     private var recreateTransitionData: TransitionData? = null
 *
 *     override fun onCreate(savedInstanceState: Bundle?) {
 *         super.onCreate(savedInstanceState)
 *         setContentView(R.layout.activity_main)
 *
 *         initView()
 *         // 重建过渡动画
 *         if (savedInstanceState != null)
 *             savedInstanceState.getParcelable<TransitionData>(TRANSITION_DATA_KEY)?.let {
 *                 transitionAnimation(it)
 *             }
 *     }
 *
 *     override fun onSaveInstanceState(outState: Bundle) {
 *         super.onSaveInstanceState(outState)
 *
 *         if (recreateTransitionData != null) {
 *             // 保存重建过渡动画 data
 *             outState.putParcelable(TRANSITION_DATA_KEY, recreateTransitionData)
 *         }
 *     }
 *
 *     /**
 *      * 使用过渡动画重建（recreate）Activity
 *      */
 *     private fun transitionRecreate(type: TransitionType) {
 *         // 获取切换主题menu的坐标（以menu的中心点为圆形揭露动画的中心点）
 *         val menuItemView = toolbar.menu.findItem(R.id.menu_theme_toggle).let {
 *             toolbar.findViewById<View>(it.itemId)
 *         }
 *         val location = IntArray(2)
 *         menuItemView.getLocationOnScreen(location)
 *         val centerX = location[0] + menuItemView.width / 2f
 *         val centerY = location[1] + menuItemView.height / 2f
 *         // Activity截图
 *         val screenBitmap = window.decorView.drawToBitmap()
 *         recreateTransitionData = TransitionData(centerX, centerY, screenBitmap, type)
 *         // 重建Activity
 *         recreate()
 *     }
 *
 *     /**
 *      * 过渡动画
 *      */
 *     private fun transitionAnimation(transitionData: TransitionData) {
 *         ivTransition.visibility = View.VISIBLE
 *         ivTransition.setImageBitmap(transitionData.screenBitmap)
 *
 *         ivTransition.post {
 *             val animator = ValueAnimator.ofFloat()
 *             var clipType = ClipImageView.ClipType.CIRCLE
 *             when (transitionData.type) {
 *                 TransitionType.ENTER -> {
 *                     // 进入动画，裁切掉圆内的区域 圆由小变大
 *                     animator.setFloatValues(
 *                         0f,
 *                         hypot(ivTransition.width.toFloat(), ivTransition.height.toFloat())
 *                     )
 *                     clipType = ClipImageView.ClipType.CIRCLE_REVERSE
 *                 }
 *
 *                 TransitionType.EXIT -> {
 *                     // 退出动画，裁切掉圆外的区域 圆由大变小
 *                     animator.setFloatValues(
 *                         hypot(
 *                             ivTransition.width.toFloat(),
 *                             ivTransition.height.toFloat()
 *                         ),
 *                         0f
 *                     )
 *                     clipType = ClipImageView.ClipType.CIRCLE
 *                 }
 *             }
 *             animator.duration =
 *                 resources.getInteger(android.R.integer.config_longAnimTime).toLong()
 *             animator.addListener(
 *                 onEnd = {
 *                     // 动画结束后隐藏 ImageView
 *                     ivTransition.visibility = View.GONE
 *                 }
 *             )
 *             animator.addUpdateListener {
 *                 val radius = it.animatedValue as Float
 *                 // 更新裁切区域
 *                 ivTransition.clipCircle(
 *                     transitionData.centerX,
 *                     transitionData.centerY,
 *                     radius,
 *                     clipType
 *                 )
 *             }
 *             animator.start()
 *         }
 *     }
 *
 *     private fun initView() {
 *         toolbar = findViewById(R.id.toolbar)
 *         toolbar.setOnMenuItemClickListener(this)
 *         ivTransition = findViewById(R.id.iv_transition)
 *
 *         val localNightMode = delegate.localNightMode
 *         val menuThemeToggle = toolbar.menu.findItem(R.id.menu_theme_toggle)
 *         if (localNightMode == AppCompatDelegate.MODE_NIGHT_YES) {
 *             menuThemeToggle.setIcon(R.drawable.daytime)
 *             menuThemeToggle.setTitle(R.string.daytime)
 *         } else {
 *             menuThemeToggle.setIcon(R.drawable.nighttime)
 *             menuThemeToggle.setTitle(R.string.nighttime)
 *         }
 *     }
 *
 *     override fun onMenuItemClick(item: MenuItem?): Boolean {
 *         when (item?.itemId) {
 *             R.id.menu_theme_toggle -> {
 *                 val localNightMode = delegate.localNightMode
 *                 val theme = if (localNightMode == AppCompatDelegate.MODE_NIGHT_YES) {
 *                     AppTheme.LIGHT
 *                 } else {
 *                     AppTheme.DARK
 *                 }
 *                 if (delegate.localNightMode == theme.mode) {
 *                     return true
 *                 }
 *                 AppGlobals.setTheme(theme)
 *                 // 使用过渡动画重建Activity
 *                 transitionRecreate(
 *                     // 根据当前主题设置过渡动画类型
 *                     if (theme == AppTheme.DARK)
 *                         TransitionType.ENTER
 *                     else
 *                         TransitionType.EXIT
 *                 )
 *                 return true
 *             }
 *         }
 *         return false
 *     }
 *
 */